<template>
  <div class="home-container">
    <!-- 头部标签 -->
    <van-nav-bar fixed>
      <template #left>
        <img class="logo" src="@/assets/images/logo.png" alt="logo" />
      </template>
      <template #right>
        <!-- 编程式 -->
        <!-- <van-icon
          name="search"
          size="0.48rem"
          color="#fff"
          @click="$router.push('/search')"
        /> -->
        <!-- 声明式 -->
        <router-link to="/search">
          <van-icon name="search" size="0.48rem" color="#fff" />
        </router-link>
      </template>
    </van-nav-bar>
    <!-- 频道列表 -->
    <van-tabs v-model="channelId" animated sticky offset-top="1.226667rem">
      <!-- v-for循环生成频道列表 -->
      <van-tab
        v-for="obj in userChannelList"
        :key="obj.id"
        :title="obj.name"
        :name="obj.id"
      >
        <!-- 下拉刷新 -->
        <van-pull-refresh
          v-model="isLoading"
          success-text="刷新成功"
          @refresh="pullDownRefreshFn"
        >
          <!-- 上拉加载更多 -->
          <van-list
            v-model="loading"
            :finished="done"
            finished-text="我是有底线滴!"
            :immediate-check="false"
            offset="50"
            @load="pullUpLoadMoreFn"
          >
            <article-list :list="articleList" @dislike="dislikeFn" />
          </van-list>
        </van-pull-refresh>
      </van-tab>
    </van-tabs>
    <!-- +号 -->
    <van-icon
      name="plus"
      size="0.45rem"
      class="moreChannels"
      @click="show = true"
    />
    <!-- 弹出层组件 -->
    <van-popup v-model="show" class="edit_wrap">
      <!-- 弹出层的主体区域 -->
      <channel-edit
        :selectedChannelList="userChannelList"
        @close-popup="show = false"
        @add-channel="addChannelFn"
        @del-channel="delChannelFn"
        @switch-channel="switchChannelFn"
      />
    </van-popup>
  </div>
</template>

<script>
// 目标：频道文章列表组件结构铺设
// 1. 观察Home/index.vue的频道列表结构，拆分组件
// 2. 拆分两个组件，ArticleList 和 ArticleItem
// 3. 因为需要共用，所以把ArticleList 和 ArticleItem全局注册
// 4. 组装组件结构，ArticleItem -> ArticleList -> Home

// 目标：文章列表数据渲染
// 1. 定义接口
// 2.在Home/index.vue调接口 -> 父传子 -> 文章列表传给 ArticleList
// 3. ArticleList循环生成ArticleItem -> 父传子 -> ArticleItem
// 4. ArticleItem 拿到文章对象，把对象指定的属性放在指定的标签位置

// 目标：文章列表-上拉加载更多
// 1. 使用van-list组件，准备属性和方法
// 2. 每次触底的时候，发送新的请求，获取下一页数据
// 3. 把旧新数据（数组）合并到一起
// 4. MVVM的思想，数据变了 -> 驱动视图的更新

// 目标：切换频道报一个key重复的问题
// 问题的原因：切换频道的时候，在watch 和 上拉触底两处发了一样的请求，
// 导致数据重复
// 解决办法：
// 1. 在切换频道的时候，把上拉的状态和文章列表都重置为初始状态
// 2. 在上拉触底加个判断，文章列表数组有值，在触发触底请求

// 目标：下拉刷新
// 1. van-pull-refresh组件，准备属性和事件
// 2.在下拉组件的refresh事件中，发请求，拿新数据
// 3.用新数据，替换旧数据

// 目标：首页滚动条位置恢复
// 1. 离开首页之前，保存滚动条位置
// 组件内的路由守卫 -> beforeRouteLeave(to, from, next) -> window.scrollY -> 保存滚动条位置
// 2.下次进入首页的时候，让窗口滚动到指定的位置即可
// activated -> window.scrollTo(x, y)
import {
  getUserChannelListAPI,
  getArticleListAPI,
  updateUserChannelListAPI
} from '@/api/Home'
import ChannelEdit from './ChannelEdit.vue'
export default {
  name: 'Home',
  components: { ChannelEdit },
  data () {
    return {
      userChannelList: [], // 用户选择的频道列表
      channelId: 0, // 当前激活（选中）的频道id，默认值是零，表示推荐频道
      articleList: [], // 文章列表
      loading: false, // 上拉每一页的加载状态
      done: false, // 整个上拉的加载状态
      isLoading: false, // 控制下拉刷新的加载状态
      show: false // 控制频道管理弹出层可见性
    }
  },
  computed: {
    // 计算得到新的频道列表 -> 作为接口参数
    channels () {
      // reudce 或 map + filter
      /* return this.userChannelList.reduce((sum, obj, index) => {
        构造一个新对象
        const item = {
          id: obj.id,
          seq: index + 1
        }
        推荐频道排除
        if (item.id !== 0) {
          sum.push(item)
        }
        return sum
      }, []) */

      // filter + map
      return this.userChannelList
        .filter((item) => item.id !== 0)
        .map((item, index) => {
          return {
            id: item.id,
            seq: index
          }
        })
    }
  },
  watch: {
    // 频道id变化时，触发侦听器
    channelId () {
      // 切换频道的时候，把状态重置，每个频道是独立的
      this.loading = false
      this.done = false
      this.timestamp = undefined
      this.articleList = []
      // 根据新的频道id，发送请求，
      this.getArticleList()
      // 获取最新频道的数据，覆盖之前的文章列表即可
    }
  },
  async created () {
    // 获取用户选择的频道列表
    const resp = await getUserChannelListAPI()
    this.userChannelList = resp.data.channels
    // 获取文章列表
    this.getArticleList()
  },
  activated () {
    // window.scrollTo(x, y)
    window.scrollTo(0, this.scrollY)
  },
  // 这里拿不到滚动条的位置
  // activated、deactivated配置keep-alive使用的，
  // 组件缓存只会缓存组件的数据（比如data，props...)，
  // 并不会缓存DOM信息，所以获取不到
  // deactivated () {
  //   console.log(window.scrollY)
  // },
  // 导航离开该组件的对应路由时调用
  beforeRouteLeave (to, from, next) {
    this.scrollY = window.scrollY
    // 放行
    next()
  },

  methods: {
    // 获取文章列表，传参，让其上拉、下拉重用
    async getArticleList (isPullUp = true) {
      // 2.获取选中频道的文章列表
      const resp = await getArticleListAPI({
        channelId: this.channelId,
        // 这里timestamp传入undefined的目的是跟后续接口参数保持一致，
        // undefined表示没传，就可以走系统默认时间戳
        timestamp: this.timestamp
      })
      const {
        data: { results, pre_timestamp }
      } = resp
      // 判断，没有则加载终止，把剩余的数据也合并到文章列表数组中
      if (pre_timestamp === null) {
        this.done = true
        this.articleList = [...this.articleList, ...results]
        return
      }
      // 有数据则合并
      // 在模板标签中需要使用的数据，需要存储到data变量中
      this.articleList = isPullUp ? [...this.articleList, ...results] : results

      // 这里的timestamp属性因为不需要在模板标签中使用，只是把它保存起来，
      // 传递给后台接口
      this.timestamp = pre_timestamp
      // 数据更新完毕，需要手动把loading设置为false，
      // 目的是可以继续请求下一页数据了
      this.loading = false
      this.isLoading = false
    },
    // 上拉加载更多
    pullUpLoadMoreFn () {
      if (!this.articleList.length) return
      this.getArticleList()
    },
    // 下拉刷新
    pullDownRefreshFn () {
      // 暂时没有下拉刷新接口，所以用上拉加载更多的接口模拟
      // 1. 发请求，拿新数据
      this.getArticleList(false)
      // 2. 新数据替换旧数组
    },
    // 文章 - 不感兴趣
    dislikeFn (i) {
      this.articleList.splice(i, 1)
      this.$notify({ type: 'success', message: '操作成功' })
      // 当articleList数组的长度小于6，防止漏出空白区域，
      // 再重新拉取10条数据回来，做个填充
      if (this.articleList.length <= 6) {
        this.getArticleList()
      }
    },
    // 更新频道
    async updateChannel () {
      await updateUserChannelListAPI({
        channels: this.channels
      })
      this.$notify({ type: 'success', message: '更新成功' })
    },
    // 添加频道
    addChannelFn (item) {
      // 1. vue变量
      this.userChannelList.push(item)
      // 2. 同步到后台
      this.updateChannel()
    },
    // 删除频道
    delChannelFn (index) {
      // 1. vue变量
      this.userChannelList.splice(index, 1)
      // 2. 同步到后台
      this.updateChannel()
    },
    // 切换频道
    switchChannelFn (cId) {
      this.channelId = cId
      // 关闭弹出层
      this.show = false
    }
  }
}
</script>

<style scoped lang="less">
.logo {
  width: 100px;
  height: 30px;
}
/* tab内容距离tab导航的距离 */
/deep/ .van-tabs__content {
  padding-top: 44px;
}

// 设置 tabs 容器的样式
/deep/ .van-tabs__wrap {
  padding-right: 20px;
  background-color: #fff;
}
// 设置小图标的样式
.moreChannels {
  position: fixed;
  top: 60px;
  right: 8px;
  z-index: 999;
}
/* 频道编辑弹出层铺满屏幕 */
.edit_wrap {
  width: 100%;
  height: 100%;
}
</style>
